ZooKeeper 如何保证数据一致性?
0. 引言
ZooKeeper 是分布式协调服务的标杆(配置中心、分布式锁、服务注册、选主),其一致性由 ZAB(ZooKeeper Atomic Broadcast)协议保证——一种面向"崩溃恢复 + 主备广播"的共识协议,与 Paxos 同源但更聚焦:所有写操作由 Leader 串行广播,Follower 按序应用,保证全局顺序一致性。本文拆解 ZAB 的状态机四阶段与选主细节。
1. ZAB 协议整体视图
ZAB 将节点状态机划分为四个阶段:
图表渲染中…
| 阶段 | 作用 | 关键点 |
|---|---|---|
| ELECTION(选举) | 选出新 Leader | FastLeaderElection:比较 epoch 与 zxid,得票过半胜出 |
| DISCOVERY(发现) | 准 Leader 收集各节点最新提案 | 通过 NEWLEADER/FOLLOWERINFO 交换已接受的最大 zxid |
| SYNCHRONIZATION(同步) | 数据追赶,保证新 Leader 拥有所有已提交提案 | 缺少的提案从 Leader 处补齐,对齐后再进入广播 |
| BROADCAST(广播) | 正常服务期:写请求按序广播、多数派 ack 即提交 | 与 2PC 类似的 Leader-COHORT 两阶段 |
2. 选举阶段:FastLeaderElection
触发条件:集群启动、Leader 崩溃、Leader 失去多数派连接。
- 每个节点投自己一票
(myid, zxid, epoch),向所有节点广播; - 收到他人选票后,PK 规则(epoch 大的胜;同 epoch 比 zxid 大的胜;同 zxid 比 myid 大的胜)更新自己的投票并广播;
- 某节点获得超过半数选票 → 广播结果,成为准 Leader;
- 其余节点收到多数派结果后收敛投票。
图表渲染中…
为什么比 zxid 而不是比数据量? zxid 是"事务编号",越大代表数据越新;选 zxid 最大的节点当 Leader,可最小化同步阶段的数据追赶量。zxid 是 64 位:高 32 位是 epoch(Leader 任期),低 32 位是事务序号——保证跨任期的全局有序。
3. 同步阶段:数据追赶
新 Leader 选出后必须保证自己拥有所有已提交事务:
- Follower 上报自己已接受的最大 zxid;
- Leader 找出各 Follower 缺失的提案,将自身事务日志中的提案补发给 Follower(以及尚未提交的历史提案);
- Follower 按序应用补齐后 ack,Leader 确认过半完成同步后广播
NEWLEADER提交,集群进入 BROADCAST。
若新 Leader 自身也缺提案(极端情况:多数派中 zxid 最大者缺历史提交),ZAB 会"回退":丢弃未提交的提案,保证已提交的绝不少、未提交的绝不乱。
4. 广播阶段:写请求的两阶段
图表渲染中…
- 写请求无论打到哪个节点,最终都转发到 Leader;
- Leader 分配递增 zxid,先写本地事务日志,再广播
PROPOSAL; - 收到多数派 ACK 后发送
COMMIT并返回客户端成功——这是 ZooKeeper 强一致(线性化写)的来源; - Follower 按 zxid 顺序应用,保证全局顺序一致性。
5. ZooKeeper 的读一致性与性能折中
| 读方式 | 一致性 | 说明 |
|---|---|---|
| 默认读(follower 本地读) | 顺序一致(可能读到旧值) | 高性能,用于非关键数据(如服务列表快照) |
sync 后读 | 接近线性一致 | 读前先与 Leader 同步追赶 |
| 写读(写后立即读同节点) | 强一致 | 写请求返回即代表多数派已提交 |
工程启示:ZooKeeper 的"一致性"主要指写路径的线性化 + 全序;默认读是允许旧值的(这也是它被调侃"不是强一致读"的原因)。对读一致性要求极高的场景(如分布式锁校验),使用
sync+ 读。
6. 常见问题
- ZAB 与 Paxos 的区别:ZAB 面向"主备 + 广播",天然有 Leader 且聚焦顺序(zxid 全序);Paxos 面向"多个值达成共识",无固定 Leader。ZAB 被广泛认为是 Paxos 的变体,但流程上与 Multi-Paxos 有明显差异(如两阶段广播、epoch 机制)。
- 写性能瓶颈:所有写走 Leader 串行广播,写吞吐受 Leader 单点限制(约万级 TPS)——读多写少的协调场景够用。
- n 个节点最多挂几个:多数派原则,5 节点可挂 2 个;奇数节点部署(避免平票)。
- zk 3.8+ 特性:支持
follower写(follower转 Leader 的代理优化)、learning节点、leader election算法扩展(FastLeaderElection之外可选LeaderElection)。
7. 小结
- ZAB = 选举 → 发现 → 同步 → 广播四阶段状态机,核心是"Leader 串行广播 + 多数派提交 + zxid 全序";
- FastLeaderElection 按
epoch > zxid > myid的 PK 规则过半胜出; - 写路径线性化(多数派 ACK 即提交),默认读路径顺序一致(可能旧值);
- ZooKeeper 是 CP 系统:分区时少数派侧拒绝服务,保证不出现双 Leader(fencing 机制)。
下一章讲解分布式事务解决方案全景:2PC、3PC、TCC、消息事务与 Saga。